package com.zygh.lz.util;

import cn.hutool.core.date.DateUtil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

public class DateUtils {

    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");

    /**
     * 获取某月的最后一天
     */
    public static String getLastDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        //设置年份
        cal.set(Calendar.YEAR, year);
        //设置月份
        cal.set(Calendar.MONTH, month - 1);
        //获取某月最大天数
        int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        //设置日历中月份的最大天数
        cal.set(Calendar.DAY_OF_MONTH, lastDay);
        //格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String lastDayOfMonth = sdf.format(cal.getTime());

        return lastDayOfMonth;
    }

    /**
     * 获取指定某一天的开始时间戳
     *
     * @param timeStamp 毫秒级时间戳
     * @param timeZone  如 GMT+8:00
     * @return
     */
    public static String getDailyStartTime(Long timeStamp, String timeZone) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(TimeZone.getTimeZone(timeZone));
        calendar.setTimeInMillis(timeStamp);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        long timeInMillis = calendar.getTimeInMillis();
        String s = String.valueOf(timeInMillis);
        String substring = s.substring(0, s.length() - 3);
        return substring;
    }

    /**
     * 获取指定某一天的结束时间戳
     *
     * @param timeStamp 毫秒级时间戳
     * @param timeZone  如 GMT+8:00
     * @return
     */
    public static String getDailyEndTime(Long timeStamp, String timeZone) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(TimeZone.getTimeZone(timeZone));
        calendar.setTimeInMillis(timeStamp);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        long timeInMillis = calendar.getTimeInMillis();
        String s = String.valueOf(timeInMillis);
        String substring = s.substring(0, s.length() - 3);
        return substring;
    }


    /**
     * @param startTime
     * @param endTime
     * @return 返回开始时间和结束时间之间的每一日
     * @throws ParseException
     */
    public static GregorianCalendar[] getDate(String startTime, String endTime) throws ParseException {
        Vector<GregorianCalendar> v = new Vector<GregorianCalendar>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        GregorianCalendar gc1 = new GregorianCalendar(), gc2 = new GregorianCalendar();
        gc1.setTime(sdf.parse(startTime));
        gc2.setTime(sdf.parse(endTime));
        do {
            GregorianCalendar gc3 = (GregorianCalendar) gc1.clone();
            v.add(gc3);
            gc1.add(Calendar.DAY_OF_MONTH, 1);
        } while (!gc1.after(gc2));
        return v.toArray(new GregorianCalendar[v.size()]);
    }


    //按格式获取时间
    public static String eiditime(GregorianCalendar e) {
        String curdate = e.get(Calendar.YEAR) + "";
        if ((e.get(Calendar.MONTH) + 1) < 10) {
            curdate = curdate + "0" + (e.get(Calendar.MONTH) + 1);
        } else {
            curdate = curdate + (e.get(Calendar.MONTH) + 1);
        }
        if (e.get(Calendar.DAY_OF_MONTH) < 10) {
            curdate = curdate + "0" + e.get(Calendar.DAY_OF_MONTH);
        } else {
            curdate = curdate + e.get(Calendar.DAY_OF_MONTH);
        }
        return curdate;

    }


    /**
     * 获取时间段内的 年-月-日  日期
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return List
     */
    public static List getStartEnd(String startTime, String endTime) throws ParseException {
        GregorianCalendar[] ga = getDate(startTime, endTime);
        List list = new ArrayList();
        for (GregorianCalendar e : ga) {
            String months = null;
            String days = null;
            int month = e.get(Calendar.MONTH) + 1;
            if (month < 10) {
                months = "0" + month;
            } else {
                months = String.valueOf(month);
            }
            int day = e.get(Calendar.DAY_OF_MONTH);
            if (day < 10) {
                days = "0" + day;
            } else {
                days = String.valueOf(day);
            }
            String time = e.get(Calendar.YEAR) + "-"
                    + (months) + "-" +
                    days;
            list.add(time);
        }
        return list;
    }

    //根据传入时间获取当天结束时间
    public static Date getDayEnd(Date date) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 59);
        return cal.getTime();
    }

    //根据传入时间获取当天开始时间
    public static Date getDayStart(Date date) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 00);
        cal.set(Calendar.MINUTE, 00);
        cal.set(Calendar.SECOND, 00);
        cal.set(Calendar.MILLISECOND, 00);
        return cal.getTime();
    }


    /**
     * 根据某时间段，返回起始时间内每天的起始时间
     *
     * @param startTime 开始时间  2021-12-01 00:00:00
     * @param endTime   结束时间  2021-12-07 23:00:00
     * @return List<Map>
     * @throws ParseException
     */
    public static List<Map> getDayStartDate(String startTime, String endTime) throws ParseException {
        Calendar calendar = Calendar.getInstance();
        List startEnd = DateUtils.getStartEnd(startTime, endTime);
        List<Map> list = new ArrayList<>();

        for (int i = 0; i < startEnd.size(); i++) {
            Map map = new HashMap();
            String format = simpleDateFormat.format(DateUtil.parse(startEnd.get(i).toString()));
            calendar.setTime(DateUtil.parse(startEnd.get(i).toString()));
            calendar.add(Calendar.DATE, 1);
            map.put("dayStart", format);
            map.put("dayEnd", simpleDateFormat.format(calendar.getTime()));
            list.add(map);
        }
        return list;
    }

    public static SimpleDateFormat sdf() {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    }

    //获取当天的开始时间
    public static String getDayBegin() {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return sdf().format(cal.getTime());
    }


    //获取当天的结束时间
    public static String getDayEnd() {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return sdf().format(cal.getTime());
    }

    //获取昨天的开始时间
    public static String getBeginDayOfYesterday() {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        cal.add(Calendar.DAY_OF_MONTH, -1);
        return sdf().format(cal.getTime());
    }

    //获取昨天的结束时间
    public static String getEndDayOfYesterDay() {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.add(Calendar.DAY_OF_MONTH, -1);
        return sdf().format(cal.getTime());
    }

    // 获得本周一0点时间
    public static String getTimesWeekmorning() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
        Calendar c = Calendar.getInstance();
        int day_of_week = c.get(Calendar.DAY_OF_WEEK) - 1;
        if (day_of_week == 0)
            day_of_week = 7;
        c.add(Calendar.DATE, -day_of_week + 1);
        return format.format(c.getTime());
    }

    // 获得本周日24点时间
    public static String getTimesWeeknight() {
        SimpleDateFormat formatDate = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
        Calendar c = Calendar.getInstance();
        int day_of_week = c.get(Calendar.DAY_OF_WEEK) - 1;
        if (day_of_week == 0)
            day_of_week = 7;
        c.add(Calendar.DATE, -day_of_week + 7);
        return formatDate.format(c.getTime());
    }

    //根据当前日期获得最近n周的日期区间（不包含本周）
    public static String getFromToDate(SimpleDateFormat sdf, Date date, int n, int option, int k) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        int offset = 0 == option ? 1 - dayOfWeek : 7 - dayOfWeek;
        int amount = 0 == option ? offset - (n - 1 + k) * 7 : offset - k * 7;
        calendar.add(Calendar.DATE, amount);
        return sdf.format(calendar.getTime());
    }

    // 获取上周的开始时间
    public static String getBeginDayOfLastWeek() {
        //上周日期
        SimpleDateFormat sdf = sdf();
        String beginDate = getFromToDate(sdf, new Date(), 1, 0, 1);

        Calendar calendar = Calendar.getInstance();
        try {
            calendar.setTime(sdf.parse(beginDate));
        } catch (Exception e) {
            e.printStackTrace();
        }
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return sdf.format(calendar.getTime());
    }

    // 获取上周的结束时间
    public static String getEndDayOfLastWeek() {
        //上周日期
        SimpleDateFormat sdf = sdf();
        String endDate = getFromToDate(sdf, new Date(), 1, 1, 1);

        Calendar calendar = Calendar.getInstance();
        try {
            calendar.setTime(sdf.parse(endDate));
        } catch (Exception e) {
            e.printStackTrace();
        }
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return sdf.format(calendar.getTime());
    }

    // 获得本月第一天0点时间
    public static String getTimesMonthmorning() {
        Calendar cal = Calendar.getInstance();
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
        return sdf().format(cal.getTime());
    }

    // 获得本月最后一天24点时间
    public static String getTimesMonthnight() {
        Calendar cal = Calendar.getInstance();
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        return sdf().format(cal.getTime());
    }

    // 获得上月第一天0点时间
    public static String getTimesLastMonthmorning() {
        //上月日期
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, -1);
        SimpleDateFormat sdf = sdf();
        String gtimelast = sdf.format(c.getTime()); //上月
        int lastMonthMaxDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);
        c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), lastMonthMaxDay, 23, 59, 59);

        //按格式输出
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-01 00:00:00");
        String gtime = sdf2.format(c.getTime()); //上月第一天
        return gtime;
    }

    // 获得上月最后一天24点时间
    public static String getTimesLastMonthnight() {
        //上月日期
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, -1);
        SimpleDateFormat sdf = sdf();
        String gtimelast = sdf.format(c.getTime()); //上月
        int lastMonthMaxDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);
        c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), lastMonthMaxDay, 23, 59, 59);

        //按格式输出
        String gtime = sdf.format(c.getTime()); //上月最后一天
        return gtime;
    }

    /**
     * 获取指定月的开始时间
     * @return
     */
    public static Date getStartTimeOfCurrentMonth(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),1);
        setMinTimeOfDay(calendar);
        return calendar.getTime();
    }

    /**
     * 获取指定月的结束时间
     * @return
     */
    public static Date getEndTimeOfCurrentMonth(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.setTime(date);
        int maxMonthDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        calendar.set(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),maxMonthDay);
        setMaxTimeOfDay(calendar);
        return calendar.getTime();
    }

    /**
     * 设置当天的开始时间
     * @param calendar
     */
    private static void setMinTimeOfDay(Calendar calendar) {
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.MILLISECOND, 0);
    }

    /**
     * 设置当天的结束时间
     * @param calendar
     */
    private static void setMaxTimeOfDay(Calendar calendar) {
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.MILLISECOND, 999);
    }


    /**
     * @param nowTime   当前时间
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return
     * @author sunran   判断当前时间在时间区间内
     */
    public static boolean thinkTime(Date nowTime, Date startTime, Date endTime) {
        if (nowTime.getTime() == startTime.getTime()
                || nowTime.getTime() == endTime.getTime()) {
            return true;
        }

        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);
        Calendar begin = Calendar.getInstance();
        begin.setTime(startTime);

        Calendar end = Calendar.getInstance();
        end.setTime(endTime);

        if (date.after(begin) && date.before(end)) {
            return true;
        } else {
            return false;
        }
    }


    public static boolean isInRange(LocalDateTime startDate, LocalDateTime endDate, LocalDateTime startTime, LocalDateTime endTime) {
        // 判断是否相交
        return startDate.isBefore(endTime) && endDate.isAfter(startTime);
    }


}
